package com.ifacebox.face.track.sevice;

import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.enums.DetectMode;
import com.ifacebox.face.track.utils.DebugUtils;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.time.Duration;

/**
 * @author znn
 */
public class FaceEnginePooledService extends GenericObjectPoolConfig<FaceEngineService> implements PooledObjectFactory<FaceEngineService> {
    private final int faceMaxThreads;
    private final DetectMode detectMode;
    private FaceEnginePool faceEnginePool;

    public FaceEnginePooledService(int faceMaxThreads, DetectMode detectMode) {
        this.faceMaxThreads = faceMaxThreads > 0 ? faceMaxThreads : Runtime.getRuntime().availableProcessors();
        this.detectMode = detectMode;
        super.setMaxIdle(this.faceMaxThreads);
        super.setMinIdle(this.faceMaxThreads);
        super.setMaxTotal(this.faceMaxThreads);
        super.setMaxWait(Duration.ofSeconds(5));
        super.setJmxEnabled(false);
    }

    public FaceEnginePooledService(DetectMode detectMode) {
        this(Runtime.getRuntime().availableProcessors(), detectMode);
    }

    public int getFaceMaxThreads() {
        return this.faceMaxThreads;
    }

    public synchronized FaceEnginePool getFaceEnginePool() {
        if (this.faceEnginePool == null) {
            this.faceEnginePool = new FaceEnginePool(this, this);
        }
        return this.faceEnginePool;
    }


    @Override
    public PooledObject<FaceEngineService> makeObject() throws Exception {
        FaceEngineService faceEngineService = new FaceEngineService();
        ActiveFileInfo activeFileInfo = faceEngineService.sdkInit(this.detectMode);
        DebugUtils.debug("%s(%d)\t%s for %s by v%s and v%s expires (%tF %<tT ~ %tF %<tT)", this.detectMode.name(), faceEngineService.hashCode()
                , activeFileInfo.getSdkType(), activeFileInfo.getPlatform(), activeFileInfo.getSdkVersion(), activeFileInfo.getFileVersion()
                , Long.parseLong(activeFileInfo.getStartTime()) * 1000, Long.parseLong(activeFileInfo.getEndTime()) * 1000);
        return new DefaultPooledObject<>(faceEngineService);
    }

    @Override
    public void destroyObject(PooledObject<FaceEngineService> pooledObject) {
        FaceEngineService faceEngineService = pooledObject.getObject();
        faceEngineService.sdkDestroy();
    }


    @Override
    public void activateObject(PooledObject<FaceEngineService> pooledObject) {
    }

    @Override
    public void passivateObject(PooledObject<FaceEngineService> pooledObject) {
    }

    @Override
    public boolean validateObject(PooledObject<FaceEngineService> pooledObject) {
        return true;
    }

    public static class FaceEnginePool extends GenericObjectPool<FaceEngineService> {
        public FaceEnginePool(PooledObjectFactory<FaceEngineService> factory, GenericObjectPoolConfig<FaceEngineService> config) {
            super(factory, config);
        }
    }
}
